package com.njcb.ams.repository.dao.base;

import com.google.common.collect.Lists;
import com.njcb.ams.factory.domain.AppContext;
import com.njcb.ams.repository.dao.mapper.BaseMapper;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.util.AmsBeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;

/**
 * @param <Obj> 对象引用
 * @param <PK>  对象主键
 * @author LIUYANLONG
 */
public abstract class BaseMyBatisDAO<Obj, ObjExample, PK extends Serializable> extends SqlSessionDaoSupport implements BaseMapper<Obj, ObjExample, PK> {
    protected static final Logger logger = LoggerFactory.getLogger(BaseMyBatisDAO.class);

    public Class<Obj> entityClass;

    /**
     * 获取对应mapper对象
     * @param <T> 对象类型
     * @return BaseMapper mapper信息
     */
    public abstract <T extends BaseMapper<Obj, ObjExample, PK>> T getMapper();

    /**
     * 默认主键字段名
     */
    public static final String DEFAULT_KEY_FIELD = "id";

    @Override
    @Resource
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

    public CommDAO getCommDAO() {
        return AppContext.getBean(CommDAO.class);
    }

    @Override
    public Obj selectByPrimaryKey(PK id) {
        return getMapper().selectByPrimaryKey(id);
    }

    @Override
    public Obj selectByPrimaryKeyForUpdate(PK id) {
        return getMapper().selectByPrimaryKeyForUpdate(id);
    }

    @Override
    public Integer updateByPrimaryKey(Obj record) {
        return getMapper().updateByPrimaryKey(record);
    }

    @Override
    public Integer updateByPrimaryKeySelective(Obj record) {
        return getMapper().updateByPrimaryKeySelective(record);
    }

    @Override
    public Integer deleteByPrimaryKey(PK id) {
        return getMapper().deleteByPrimaryKey(id);
    }

    @Override
    public Long countByExample(ObjExample example) {
        return getMapper().countByExample(example);
    }

    @Override
    public Integer deleteByExample(ObjExample example) {
        return getMapper().deleteByExample(example);
    }

    @Override
    public Integer insert(Obj record) {
        return getMapper().insert(record);
    }

    @Override
    public Integer insertBatch(List<Obj> batchList) {
        if (null == batchList || batchList.size() == 0) {
            return 0;
        }
        return getMapper().insertBatch(batchList);
    }

    @Override
    public Integer insertBatchGroup(List<Obj> batchList) {
        if (null == batchList || batchList.size() == 0) {
            return 0;
        }
        List<List<Obj>> groupList = Lists.partition(batchList, 500);
        Integer succCount = 0;
        for (List<Obj> parList : groupList) {
            succCount += getMapper().insertBatch(batchList);
        }
        return succCount;
    }

    @Override
    public Integer insertSelective(Obj record) {
        return getMapper().insertSelective(record);
    }

    @Override
    public List<Obj> selectByExample(ObjExample example) {
        return getMapper().selectByExample(example);
    }

    @Override
    public List<Obj> selectBySelective(Obj record) {
        return getMapper().selectBySelective(record);
    }

    public Obj selectOneByExample(ObjExample example) {
        List<Obj> list = getMapper().selectByExample(example);
        if (null == list) {
            return null;
        } else if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() == 0) {
            return null;
        } else {
            ExceptionUtil.throwAppException("存在多余数据请检查,表为[" + example.getClass().getSimpleName()+"],条数["+list.size()+"]");
            return null;
        }
    }

    @Override
    public Integer updateByExampleSelective(Obj record, ObjExample example) {
        return getMapper().updateByExampleSelective(record, example);
    }

    @Override
    public Integer updateByExample(Obj record, ObjExample example) {
        return getMapper().updateByExample(record, example);
    }

    public int saveOrUpdateByPrimaryKey(Obj record) {
        if (AmsBeanUtils.isContainField(record.getClass(), DEFAULT_KEY_FIELD)
                && StringUtils.isNotEmpty(AmsBeanUtils.getProperty(record, DEFAULT_KEY_FIELD))
                && !"0".equals(AmsBeanUtils.getProperty(record, DEFAULT_KEY_FIELD))) {
            return getMapper().updateByPrimaryKey(record);
        } else {
            return getMapper().insert(record);
        }
    }

}
